package com.ruoyi.approval.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.approval.domain.AApprovalRequests;
import com.ruoyi.approval.domain.ASchedulingApplicationVehicle;
import com.ruoyi.approval.dto.ExecutionRequestsDto;
import com.ruoyi.approval.mapper.AApprovalRequestsMapper;
import com.ruoyi.approval.mapper.ASchedulingApplicationVehicleMapper;
import com.ruoyi.approval.param.AddExecutionRecordsParam;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.RemoteProcessLogService;
import com.ruoyi.system.api.RemoteVehiclesService;
import com.ruoyi.system.api.domain.SysProcessLog;
import com.ruoyi.system.api.domain.SysVechicleDto;
import com.ruoyi.system.api.domain.SysVehicles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.approval.mapper.AExecutionRecordsMapper;
import com.ruoyi.approval.domain.AExecutionRecords;
import com.ruoyi.approval.service.IAExecutionRecordsService;

/**
 * 申请执行记录Service业务层处理
 *
 * @author ruoyi
 * @date 2025-04-02
 */
@Service
public class AExecutionRecordsServiceImpl implements IAExecutionRecordsService {
    private static final Long VEHICLE_STATUS_FREE = 0L;
    private static final Long VEHICLE_STATUS_EXECUTING = 3L;
    private static final Long VEHICLE_STATUS_IDLE = 0L;
    private static final Long EXECUTION_TYPE = 2L;
    private static final Long EXECUTION_STATUS_STARTED = 1L;
    private static final Long EXECUTION_STATUS_ENDED = 2L;
    private static final int SUCCESS_CODE = 200;

    @Autowired
    private AExecutionRecordsMapper aExecutionRecordsMapper;

    @Autowired
    private AApprovalRequestsMapper aApprovalRequestsMapper;

    @Autowired
    private RemoteVehiclesService remoteVehiclesService;

    @Autowired
    private ASchedulingApplicationVehicleMapper aSchedulingApplicationVehicleMapper;

    @Autowired
    private RemoteProcessLogService remoteProcessLogService;

    /**
     * 查询申请执行记录
     *
     * @param approvalRequestId 申请执行记录主键
     * @return 申请执行记录
     */
    @Override
    public ExecutionRequestsDto selectAExecutionRecordsById(Long approvalRequestId) {
        // 查询申请执行记录详情
        AExecutionRecords aExecutionRecords = aExecutionRecordsMapper.selectAExecutionRequestId(approvalRequestId);
        if (aExecutionRecords == null) {
            throw new RuntimeException("未找到该申请订单");
        }
        System.out.println(aExecutionRecords.toString());

        // 查询关联的车辆调度申请
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(String.valueOf(approvalRequestId), EXECUTION_TYPE);
        if (aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("未找到该申请订单");
        }

        // 获取车辆信息
        Set<SysVehicles> sysVehicles = getSysVehiclesFromApplicationVehicles(aSchedulingApplicationVehicles);

        // 调用远程服务获取车辆详细信息
        R<Set<SysVechicleDto>> setR = remoteVehiclesService.selectVehicles(sysVehicles);
        if (SUCCESS_CODE != setR.getCode()) {
            throw new RuntimeException("有车辆信息未找到");
        }

        // 构建返回的执行请求DTO
        ExecutionRequestsDto executionRequestsDto = new ExecutionRequestsDto();
        BeanUtil.copyProperties(aExecutionRecords, executionRequestsDto);
        executionRequestsDto.setSysVechicleDto(setR.getData());
        System.out.println(executionRequestsDto.toString());
        return executionRequestsDto;
    }

    /**
     * 查询申请执行记录列表
     *
     * @param aExecutionRecords 申请执行记录
     * @return 申请执行记录列表
     */
    @Override
    public List<AExecutionRecords> selectAExecutionRecordsList(AExecutionRecords aExecutionRecords) {
        // 查询申请执行记录列表
        return aExecutionRecordsMapper.selectAExecutionRecordsList(aExecutionRecords);
    }

    /**
     * 新增申请执行记录
     *
     * @param param 申请执行记录参数
     * @return 结果
     */
    @Override
    public int insertAExecutionRecords(AddExecutionRecordsParam param) {

        // 检查审批请求ID是否为空
        if (param.getApprovalRequestId() == null) {
            throw new RuntimeException("审批请求id不能为空");
        }

        // 查询审批请求详情
        AApprovalRequests aApprovalRequests = aApprovalRequestsMapper.selectAApprovalRequestsId(param.getApprovalRequestId());
        if (aApprovalRequests == null) {
            throw new RuntimeException("不存在该申请,请去提交申请");
        }

        // 检查是否已存在该申请订单
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(param.getApprovalRequestId(), EXECUTION_TYPE);
        if (!aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("已存在该申请订单");
        }

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);

        // 获取车辆信息并设置状态为执行中
        Set<SysVehicles> sysVehicles = param.getSysVehicles();
        List<ASchedulingApplicationVehicle> schedulingApplicationVehicles = createSchedulingApplicationVehicles(param.getApprovalRequestId(), sysVehicles, EXECUTION_TYPE, VEHICLE_STATUS_EXECUTING);

        // 调用远程服务更新车辆状态
        AjaxResult ajaxResult = remoteVehiclesService.updateStatus(sysVehicles);
        if (SUCCESS_CODE != (int) ajaxResult.get("code")) {
            throw new RuntimeException("有车辆预约失败");
        }

        // 构建申请执行记录对象
        AExecutionRecords aExecutionRecords = BeanUtil.toBean(param, AExecutionRecords.class);
        aExecutionRecords.setActualStartTime(formattedDateTime);
        aExecutionRecords.setStatus(EXECUTION_STATUS_STARTED);

        // 插入车辆调度申请
        int i = aSchedulingApplicationVehicleMapper.insertASchedulingApplicationVehicleId(schedulingApplicationVehicles);
        if (i != schedulingApplicationVehicles.size()) {
            throw new RuntimeException("有车辆预约失败");
        }

        // 插入申请执行记录
        int i1 = aExecutionRecordsMapper.insertAExecutionRecords(aExecutionRecords);
        if (i1 != 1) {
            throw new RuntimeException("执行失败，请联系管理员");
        }

        // 更新审批请求状态
        aApprovalRequests.setApprovalResult(3L);
        int i2 = aApprovalRequestsMapper.updateAApprovalRequests(aApprovalRequests);
        if (i2 != 1) {
            throw new RuntimeException("执行失败，请联系管理员");
        }

        // 记录日志
        logProcess(aApprovalRequests, "开始执行", aApprovalRequests.getApproverName() + "提取了车辆，开始执行");

        return i1;
    }

    /**
     * 修改申请执行记录
     *
     * @param aExecutionRecords 申请执行记录
     * @return 结果
     */
    @Override
    public int updateAExecutionRecords(AExecutionRecords aExecutionRecords) {
        // 更新申请执行记录
        return aExecutionRecordsMapper.updateAExecutionRecords(aExecutionRecords);
    }

    /**
     * 批量删除申请执行记录
     *
     * @param ids 需要删除的申请执行记录主键
     * @return 结果
     */
    @Override
    public int deleteAExecutionRecordsByIds(Long[] ids) {
        // 批量删除申请执行记录
        return aExecutionRecordsMapper.deleteAExecutionRecordsByIds(ids);
    }

    /**
     * 结束执行记录信息
     *
     * @param approvalRequestId 申请执行记录主键
     * @return 结果
     */
    @Override
    public int deleteAExecutionRecordsById(Long approvalRequestId) {

        // 查询审批请求详情
        AApprovalRequests aApprovalRequests = aApprovalRequestsMapper.selectAApprovalRequestsId(String.valueOf(approvalRequestId));
        if (aApprovalRequests == null) {
            throw new RuntimeException("不存在该申请,请去提交申请");
        }

        // 查询申请执行记录详情
        AExecutionRecords aExecutionRecords = aExecutionRecordsMapper.selectAExecutionRequestId(approvalRequestId);
        if (aExecutionRecords == null) {
            throw new RuntimeException("未找到该申请订单");
        }

        // 查询关联的车辆调度申请
        List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles = aSchedulingApplicationVehicleMapper.selectASchedulingApplicationVehicleBySchedulingApplicationId(String.valueOf(approvalRequestId), EXECUTION_TYPE);
        if (aSchedulingApplicationVehicles.isEmpty()) {
            throw new RuntimeException("未找到该申请订单");
        }

        // 获取车辆信息并设置状态为空闲
        Set<SysVehicles> sysVehicles = getSysVehiclesFromApplicationVehicles(aSchedulingApplicationVehicles);
        updateVehicleStatus(sysVehicles, VEHICLE_STATUS_IDLE);

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);

        // 更新申请执行记录状态
        aExecutionRecords.setStatus(EXECUTION_STATUS_ENDED);
        aExecutionRecords.setActualEndTime(formattedDateTime);
        int i = aExecutionRecordsMapper.updateAExecutionRecords(aExecutionRecords);
        if (i != 1) {
            throw new RuntimeException("执行失败，请联系管理员");
        }

        // 更新审批请求状态
        aApprovalRequests.setApprovalResult(4L);
        int i2 = aApprovalRequestsMapper.updateAApprovalRequests(aApprovalRequests);
        if (i2 != 1) {
            throw new RuntimeException("执行失败，请联系管理员");
        }

        // 记录日志
        logProcess(aApprovalRequests, "结束执行", "车辆已归还");

        return i;
    }

    /**
     * 从调度申请车辆获取SysVehicles
     *
     * @param aSchedulingApplicationVehicles 调度申请车辆列表
     * @return 车辆集合
     */
    private Set<SysVehicles> getSysVehiclesFromApplicationVehicles(List<ASchedulingApplicationVehicle> aSchedulingApplicationVehicles) {
        Set<SysVehicles> sysVehicles = new HashSet<>();
        for (ASchedulingApplicationVehicle aSchedulingApplicationVehicle : aSchedulingApplicationVehicles) {
            SysVehicles sysVehicle = new SysVehicles();
            sysVehicle.setId(aSchedulingApplicationVehicle.getVehicleId());
            sysVehicles.add(sysVehicle);
        }
        return sysVehicles;
    }

    /**
     * 更新车辆状态
     *
     * @param sysVehicles 车辆集合
     * @param status      车辆状态
     */
    private void updateVehicleStatus(Set<SysVehicles> sysVehicles, Long status) {
        for (SysVehicles sysVehicle : sysVehicles) {
            sysVehicle.setStatus(status);
        }

        AjaxResult ajaxResult = remoteVehiclesService.updateStatus(sysVehicles);
        if (SUCCESS_CODE != (int) ajaxResult.get("code")) {
            throw new RuntimeException("有车辆修改状态失败");
        }
    }

    /**
     * 创建调度申请车辆
     *
     * @param approvalRequestId 审批请求ID
     * @param sysVehicles       车辆集合
     * @param type              调度类型
     * @param status            车辆状态
     * @return 调度申请车辆列表
     */
    private List<ASchedulingApplicationVehicle> createSchedulingApplicationVehicles(String approvalRequestId, Set<SysVehicles> sysVehicles, Long type, Long status) {
        List<ASchedulingApplicationVehicle> schedulingApplicationVehicles = new ArrayList<>();
        for (SysVehicles sysVehicle : sysVehicles) {
            ASchedulingApplicationVehicle aSchedulingApplicationVehicle = new ASchedulingApplicationVehicle();
            aSchedulingApplicationVehicle.setSchedulingApplicationId(approvalRequestId);
            aSchedulingApplicationVehicle.setVehicleId(sysVehicle.getId());
            aSchedulingApplicationVehicle.setType(type);
            schedulingApplicationVehicles.add(aSchedulingApplicationVehicle);
            sysVehicle.setStatus(status);
        }
        return schedulingApplicationVehicles;
    }

    /**
     * 记录操作日志
     *
     * @param aApprovalRequests 审批请求对象
     * @param operationType 操作类型
     * @param operationDetails 操作详情
     */
    private void logProcess(AApprovalRequests aApprovalRequests, String operationType, String operationDetails) {
        SysProcessLog sysProcessLog = new SysProcessLog();
        sysProcessLog.setBusinessType("审批请求");
        sysProcessLog.setBusinessId(aApprovalRequests.getApprovalRequestsId());
        sysProcessLog.setOperationType(operationType);
        sysProcessLog.setOperationTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        sysProcessLog.setOperatorId(aApprovalRequests.getApproverId());
        sysProcessLog.setOperationDetails(operationDetails);
        AjaxResult add = remoteProcessLogService.add(sysProcessLog);
        if (SUCCESS_CODE != (int) add.get("code")) {
            throw new RuntimeException("日志记录失败");
        }
    }
}
